package container

import (
	"com.yy.api/common/logger"
	"com.yy.api/common/pojo/result"
	cUtils "com.yy.api/common/utils"
	"com.yy.api/server/service"
	cS "com.yy.api/server/service/container"
	"com.yy.api/server/utils"
	"fmt"
	"strconv"
	"strings"
)

type Container struct {
	*service.BaseControllerImpl
}

func NewContainer() Container {
	return Container{
		BaseControllerImpl: &service.BaseControllerImpl{},
	}
}

func (ctrl *Container) CreateInstance() {
	logger.Default.Info("CreateInstance...")
	opts := ctrl.AddOpt("rowImage", "", result.ParseCreateInstanceRowImageError("parse rowImage failed!")).
		AddOpt("portMappings", ",").
		AddOpt("gpuNum", "1").
		AddOpt("name", "-1").
		AddOpt("userId", strconv.FormatUint(utils.GenerateTimestampBasedUserID(), 10)).
		GetOpts()
	rowImageOpt, portMappingsOpt, gpuNumOpt, nameOpt, userIdOpt := opts["rowImage"], opts["portMappings"], opts["gpuNum"], opts["name"], opts["userId"]
	// 业务逻辑
	helper, ok := cS.NewCreateInstanceHelper(portMappingsOpt, cUtils.StrToInt(gpuNumOpt))
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_CREATE_CONTAINER_ERROR, nil))
		return
	}
	defer helper.AcquireGpus()
	hostPortList := helper.GetHostPortList()
	fmt.Println(hostPortList)
	portMappingsParam := helper.GetPortMappingsParam()

	gpuIdsParam := helper.GetGpuIdsParam()
	// 检查本地镜像是否存在
	// 若不存在 尝试拉取镜像
	//if ok := cS.IsImageAvailable(rowImageOpt); !ok {
	//	if ok := cS.PullImage(rowImageOpt); !ok {
	//		ctrl.Fail(result.NewJsonResult(result.AGENT_PULL_IMAGE_ERROR, nil))
	//		return
	//	}
	//
	//}

	//**检查函数改写成异步形式
	// ---------------------------------------------------------------------------------
	//  创建容器
	cID, ok := cS.CreateContainer(rowImageOpt, portMappingsParam, gpuIdsParam, nameOpt, userIdOpt)
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_CREATE_CONTAINER_ERROR, nil))
		return
	}
	// 启动容器
	if ok := cS.StartContainer(cID); !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_START_CONTAINER_ERROR, nil))
		return
	}

	// -------------------------------------------------------------
	// 容器状态检测 改为异步形式
	// 获取容器信息
	reslt, ok := cS.InspectContainer(cID)
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_INSPECT_CONTAINER_ERROR, nil))
		return
	}

	//cS.PersistImageInfoToDB(rowImageOpt)
	//cS.PersistContainerInfoToDB(userIdOpt, hostPortList, portMappingsParam, cID)
	// 服务处理成功，返回结果 <返回容器ID即可>
	ctrl.Succeed(result.Success(reslt))
	return

}

func (ctrl *Container) ContainerList() {
	logger.Default.Info("ContainerList...")

	opts := ctrl.AddOpt("userId", "-1").
		AddOpt("displayId", "-1").
		AddOpt("status", "running").
		GetOpts()
	userIdOpt, displayIdOpt, statusOptStr := opts["userId"], opts["displayId"], opts["status"]
	reslt, ok := cS.ContainerList(userIdOpt, displayIdOpt, strings.Split(statusOptStr, ","))
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_LIST_CONTAINERS_ERROR, nil))
		return
	}
	ctrl.Succeed(result.Success(reslt))
}

func (ctrl *Container) HasContainer() {
	logger.Default.Info("HasContainer...")
	opts := ctrl.AddOpt("containerId", "", result.NewJsonResult(result.PARAM_EMPTY_ERROR, nil)).
		GetOpts()
	idOrNameOpt := opts["containerId"]
	reslt, ok := cS.HasContainer(idOrNameOpt)
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_HAS_CONTAINER_ERROR, nil))
		return
	}

	ctrl.Succeed(result.Success(reslt))
}

func (ctrl *Container) ReleaseContainer() {
	logger.Default.Info("ReleaseContainer...")
	opts := ctrl.AddOpt("containerId", "", result.NewJsonResult(result.PARAM_EMPTY_ERROR, nil)).
		GetOpts()
	idOrNameOpt := opts["containerId"]
	reslt, ok := cS.ReleaseContainer(idOrNameOpt)
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_RELEASE_CONTAINER_ERROR, nil))
		return
	}
	ctrl.Succeed(result.Success(reslt))
}

func (ctrl *Container) HealthCheckContainer() {
	logger.Default.Info("HealthCheckContainer...")
	opts := ctrl.AddOpt("containerId", "", result.NewJsonResult(result.PARAM_EMPTY_ERROR, nil)).
		GetOpts()
	idOrNameOpt := opts["containerId"]
	reslt, ok := cS.HealthCheckContainer(idOrNameOpt)
	if !ok {
		ctrl.Fail(result.NewJsonResult(result.AGENT_HEALTH_CHECK_CONTAINER_ERROR, nil))
		return
	}
	ctrl.Succeed(result.Success(reslt))
}
